<!--
Date: 2025-08-13
Copyright (c) 2025 CAX Conversion Project
-->
<template>
  <div class="choose-file">
    <div>
      <el-card class="box-card">
        <el-form ref="form1Ref" :model="formInfo" inline size="small" label-width="100" class="form_class" :rules="rules">
          <el-form-item label="业务场景:" prop="businessId">
            <el-select v-model="formInfo.businessId" clearable filterable @change="selectChange($event, 1)">
              <el-option v-for="item in businessSceneList" :key="item.id" :label="item.name" :value="item.id"></el-option>
            </el-select>
          </el-form-item>
          <el-form-item label="要素库类型:" prop="databaseId">
            <el-select v-model="formInfo.databaseId" clearable filterable @change="selectChange($event, 2)">
              <el-option v-for="item in metadataLibrarys" :key="item.id" :label="item.name" :value="item.id"></el-option>
            </el-select>
          </el-form-item>
        </el-form>
      </el-card>
      <el-card class="box-card" style="margin-top: 20px;">
        <template #header>
          <div class="card-header">
            <span>元数据管理</span>
          </div>
        </template>
        <el-form ref="form2Ref" :model="formInfo" inline size="small" label-width="100" class="form_class" :rules="rules">
          <el-form-item label="数据所有者:" prop="dataOwnerId">
            <!-- <el-input class="form_input" placeholder="请输入" v-model="formInfo.dataOwnerName" /> -->
            <el-select
              v-model="formInfo.dataOwnerId"
              filterable
              remote
              reserve-keyword
              placeholder="请输入关键词"
              :remote-method="remoteMethod"
              @change="userChange"
              :loading="loading">
              <el-option
                v-for="item in userList"
                :key="item.userId"
                :label="item.nickName"
                :value="item.userId">
              </el-option>
            </el-select>
          </el-form-item>
          <el-form-item label="数据安全级别:" prop="dataSafeLevel">
            <el-select v-model="formInfo.dataSafeLevel" placeholder="请选择" clearable>
              <el-option v-for="(val, key) in safeLevelDicts" :key="key" :value="key" :label="val"></el-option>
            </el-select>
          </el-form-item>
          <el-form-item label="数据保留政策:" prop="dataRetentionPolicy">
            <el-select v-model="formInfo.dataRetentionPolicy" placeholder="请选择" clearable>
              <el-option v-for="(val, key) in dataOwnerDicts" :key="key" :value="key" :label="val"></el-option>
            </el-select>
          </el-form-item>
        </el-form>
      </el-card>
      <div class="load-excel">
        <el-upload
          ref="upload"
          action
          accept=".xlsx,.xls,.xlsm"
          :show-file-list="true"
          :auto-upload="false"
          :limit="1"
          :on-exceed="handleExceed"
          :on-change="handle"
        >
          <template #trigger>
            <el-button size="small" type="primary" :icon="Plus" plain>选择文件</el-button>
          </template>
        </el-upload>
        <el-button v-if="loadFile" type="primary" link style="font-size: 14px" @click="openCheckDialog">点击查看数据质量报告</el-button>
      </div>
      <el-tabs
        v-model="activeName"
        type="card"
        class="sheet-tabs"
        @tab-click="handleClick"
      >
        <el-tab-pane v-for="(item, index) in sheetNames" :label="item" :name="item" :key="index">
          <el-table
            v-loading="loading"
            border
            :data="tableData"
          >
            <el-table-column
              v-for="(item, index) in title"
              :key="index"
              :prop="'in' + index"
              :label="item"
            />
          </el-table>
        </el-tab-pane>
      </el-tabs>
    </div>
    <el-dialog
      v-model="dialogVisible"
      title="数据质量报告"
      width="1000px"
      :before-close="handleClose"
    >
      <!-- <span>This is a message</span> -->
      <div class="result-all">
        <div class="left-params">
          <label class="des" for="">选择待检测Sheet页以及待检测字段：</label>
          <el-checkbox-group
            v-model="checkedSheets"
            @change="handleCheckedCitiesChange"
          >
            <el-checkbox v-for="(val, key) in chooseTableHeaderMap" :key="key" :label="key">{{
              key
            }}</el-checkbox>
          </el-checkbox-group>
          <div class="table">
            <template v-for="(val, key) in chooseTableHeaderMap">
              <label :key="key" v-if="checkedSheets.includes(key)" class="des" for="">sheet：{{ key }}</label>
              <table :key="key" v-if="checkedSheets.includes(key)" style="width: 100%;margin-bottom: 20px;" border="1" cellspacing="1">
                <thead>
                  <tr>
                    <th>序号</th>
                    <th>字段名称</th>
                    <th>时间检测</th>
                    <th>异常检测</th>
                  </tr>
                </thead>
                <tbody>
                  <tr v-for="(item, index) in val" :key="index">
                    <td>{{ index + 1 }}</td>
                    <td>{{ item.label }}</td>
                    <td><el-checkbox v-model="item.isTimeCheck" size="small" /></td>
                    <td><el-checkbox v-model="item.isOutlierCheck" size="small" /></td>
                  </tr>
                </tbody>
              </table>
            </template>
          </div>
        </div>
        <div class="right-result">
          <el-tabs v-model="qualityTab" class="demo-tabs" >
            <el-tab-pane v-for="(tab, index) in qualityResult" :label="tab.sheet_name" :name="index" :key="index">
              <el-row :key="index" :gutter="12">
                <el-col style="margin-bottom: 10px;"  :span="8">
                  <el-card shadow="always"> 字段数量：{{ tab.number_of_columns }} </el-card>
                </el-col>
                <el-col style="margin-bottom: 10px;"  :span="8">
                  <el-card shadow="always"> 空值行数量：<strong style="color:red;">{{ tab.rows_with_nulls }}</strong> </el-card>
                </el-col>
                <el-col style="margin-bottom: 10px;" :span="8">
                  <el-card shadow="always"> 总行数量：{{ tab.total_number_of_rows }} </el-card>
                </el-col>
                 <el-col style="margin-bottom: 10px;" :span="24">
                  <el-card shadow="always"> 数据类型不一致的字段数量：<strong style="color:red;">{{ tab.inconsistent_columns_count }}</strong> </el-card>
                </el-col>
                <el-col style="margin-bottom: 10px;" :span="24">
                  <el-card shadow="always"> 数据类型不一致的字段：{{ tab.inconsistent_columns.join('，') }} </el-card>
                </el-col>
                <el-col style="margin-bottom: 10px;" :span="24">
                  <el-card shadow="always"> 包含异常值的字段：{{ tab.oulier_check.join('，') }} </el-card>
                </el-col>
                <el-col style="margin-bottom: 10px;" :span="24">
                  <el-card shadow="always"> 时间字段：{{ tab.time_check }} </el-card>
                </el-col>
              </el-row>
            </el-tab-pane>
          </el-tabs>
        </div>
      </div>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="dialogVisible = false">返回</el-button>
          <el-button type="primary" @click="checkExcel">开始检测</el-button>
        </span>
      </template>
    </el-dialog>
  </div>
</template>
<script  setup name="ChooseFile">
import * as XLSX from 'xlsx';
import axios from 'axios';
import { getToken } from '@/utils/auth';
import { Plus } from '@element-plus/icons-vue';
import { genFileId } from 'element-plus';
import { getDicts } from '@/api/system/dict/data';
import { listUser } from '@/api/system/user';
import { getBusinessSceneDefinitionList, getMetadataDatabaseList, getMetadataDatabaseListByBusinessSceneCode } from '@/api/metaData';
// import { qualityResult } from './excelQualityRes.js';
const formInfo = ref({
  businessId: '',
  databaseId: '',
  databaseName: '',
  dataOwnerName: '',
  dataOwnerId: '',
  dataSafeLevel: '',
  dataRetentionPolicy: ''
});
const qualityResult = ref([]);
const form1Ref = ref();
const form2Ref = ref();
const isSceneOrDatabaseChange = ref(false); // 更改业务场景要素库类型重新查询表结构映射
const businessSceneList = ref([]);
const metadataLibrarys = ref([]);
const checkedSheets = ref([]); // 选中的sheet数据
const chooseTableHeaderMap = ref({}); 
const dialogVisible = ref(false);
const qualityTab = ref(0)
const title = ref([]); // sheet表头
const tableData = ref([]); // sheet数据
const activeName = ref(''); // 当前选中sheet名称
const loading = ref(false);
const safeLevelDicts = ref({});
const dataOwnerDicts = ref({})
const userList = ref([]);
const userListInit = ref([]);
const rules = reactive({
  businessId: [
    { required: true, message: '请选择业务场景', trigger: 'blur' },
  ],
  databaseId: [
    { required: true, message: '请选择要素库类型', trigger: 'blur' },
  ],
  dataOwnerId: [
    { required: true, message: '请选择数据所有者', trigger: 'blur' },
  ],
  dataSafeLevel: [
    { required: true, message: '请选择数据安全级别', trigger: 'blur' },
  ],
  dataRetentionPolicy: [
    { required: true, message: '请选择数据保留政策', trigger: 'blur' },
  ],
})
function readFile(file) {
  return new Promise((resolve) => {
    let reader = new FileReader();
    reader.readAsBinaryString(file);
    reader.onload = (ev) => {
      resolve(ev.target.result);
    };
  });
}
// 文件处理
const loadFile = ref(null); // 上传文件
const fileData = ref(null);  // 
const sheetNames = ref([]);
const workbook = ref(null);
const sheetsDataMap = ref({});
const titleMap = ref({});
const upload = ref();

const handleCheckedCitiesChange = () => {
  // choseTableHeaderList.value = 
}
const selectChange = (val, type) => {
  isSceneOrDatabaseChange.value = true;
  if (type == 1) {
    if (val) {
      metadataLibrarys.value = [];
      formInfo.value.databaseId = '';
      getMetadataLibrary(val);
    }
  } else {
    formInfo.value.databaseName = metadataLibrarys.value.find(item => item.id == val)?.name || '';
  }
}
// excel检测
const checkExcel = () => {
  const fm = new FormData();
  let timeCheck = {}, outlierCheck = {};
  for(let key in chooseTableHeaderMap.value) {
    if (checkedSheets.value.includes(key)) {
      timeCheck[key] = chooseTableHeaderMap.value[key].filter(item => item.isTimeCheck).map(item => item.label)
    }
    if (checkedSheets.value.includes(key)) {
      outlierCheck[key] = chooseTableHeaderMap.value[key].filter(item => item.isOutlierCheck).map(item => item.label)
    }
  }
  
  fm.append('file', loadFile.value);
  fm.append('timeCheck', JSON.stringify(timeCheck));
  fm.append('outlierCheck', JSON.stringify(outlierCheck));
  
  let VITE_APP_BASE_API = '/dev-api';
  if (import.meta.env.MODE === 'production') {
    VITE_APP_BASE_API = '/prod-api';
  }
  axios
  .post(`${VITE_APP_BASE_API}/isfd/metadataManagement/excelQuality`, fm, {
    headers: { 'Content-Type': 'multipart/form-data', 'Authorization': 'Bearer ' + getToken() }
  })
  .then((res) => {
    if (res.data.code == 200) {
      qualityResult.value = res.data.data.data_quality_report
      ElMessage({ showClose: true, message: '检测成功', type: 'success' });
    } else {
      ElMessage({ showClose: true, message: '检测失败', type: 'error' });
    }
  });
}
const openCheckDialog = () => {
  chooseTableHeaderMap.value = {};
  checkedSheets.value = [];
  qualityResult.value = [];
  for(let key in titleMap.value) {
    let tableHeaderList = titleMap.value[key].map(item => ({
      label: item,
      isTimeCheck: false,
      isOutlierCheck: false
    }))
    chooseTableHeaderMap.value[key] = tableHeaderList;
  }
  
  dialogVisible.value = true;
}
// sheet切换
const handleClick = (tab, event) => {
  loading.value = true;
  tableData.value = sheetsDataMap.value[tab.props.name];
  title.value = titleMap.value[tab.props.name];
  loading.value = false;
}
// 文件替换
const handleExceed = (files) => {
  upload.value.clearFiles();
  const file = files[0];
  file.uid = genFileId();
  upload.value.handleStart(file);
}
// 选择文件的方法
const handle = async (ev) => {
  //每次选择文件都把之前文件清空
  title.value = [];
  tableData.value = [];
  titleMap.value = {};
  let file = ev.raw; //这里面就是数据
  loadFile.value = ev.raw;
  // 将file变成二进制读取到的
  fileData.value = await readFile(file);
  // 将得到的二进制转化一下
  workbook.value = XLSX.read(fileData.value, { type: "binary" });
  // 最后把数据转成json格式的
  sheetNames.value = workbook.value.SheetNames;
  activeName.value = workbook.value.SheetNames[0];
  loading.value = true;
  // 遍历处理多sheet数据
  sheetNames.value.forEach(sheet => {
    sheetsDataMap.value[sheet] = [];
    titleMap.value[sheet] = [];
    let worksheet = workbook.value.Sheets[sheet];
    //  用XLSX.utils.sheet_to_json()方法时，可以通过设置第二个参数：defval来指定空值的默认值。例如，将defval设置为空字符串('')，这样即使单元格为空，解析后的JSON对象中也会包含这个空字符串，从而保证空值的列被正确提取出来‌
    const sheet2JSONOpts = {
      defval: '' // 给defval赋值为空的字符串
    };
    //将得到的worksheet转化为json格式
    let data = XLSX.utils.sheet_to_json(worksheet, sheet2JSONOpts);
    for (const key in data[0]) {
      titleMap.value[sheet].push(key); //获取的是标题,即每个对象的键名
    }
    data.forEach((item, index) => {
      let obj = {};
      titleMap.value[sheet].forEach((item2, index2) => {
        obj["in" + index2] = item[item2];
      });
      sheetsDataMap.value[sheet].push(obj);
    });
  })
  tableData.value = sheetsDataMap.value[activeName.value];
  title.value = titleMap.value[activeName.value];
  loading.value = false;
  isSceneOrDatabaseChange.value = true;
};
// 查询类型字典
getDicts('metadata_constants').then((res) => {
  if (res.data) {
    let levelDicts = res.data.find(item => item.dictLabel == 'data_safe_level')?.dictValue;
    let ownerDicts = res.data.find(item => item.dictLabel == 'data_retention_policy')?.dictValue;
    safeLevelDicts.value = JSON.parse(levelDicts);
    dataOwnerDicts.value = JSON.parse(ownerDicts);
  }
});
const userChange = () => {
  let fItem = userList.value.find(item => item.userId == formInfo.value.dataOwnerId);
  formInfo.value.dataOwnerName = fItem?.nickName || '';
}
function getUserList(query) {
  listUser({
    'pageNum': 1,
    'pageSize': 20,
    'userName': query
  }).then(res => {
    loading.value = false;
    if (!query) {
      userList.value = res.rows;
      userListInit.value = res.rows;
    } else {
      userList.value = res.rows;
    }
  })
}

function remoteMethod(query) {
  if (query !== '') {
    loading.value = true;
    getUserList(query)
  } else {
    userList.value = userListInit.value;
  }
}
// 获取业务场景列表
const getBusinessSceneList = () => {
  getBusinessSceneDefinitionList({pageNum: 1, pageSize: 999}).then(res => {
    businessSceneList.value = res.rows;
  })
}
// 获取要素库列表信息
const getMetadataLibrary = (sceneId) => {
  getMetadataDatabaseListByBusinessSceneCode({sceneId}).then(res => {
    metadataLibrarys.value = res.rows;
  })
}

// watch(
//   formInfo.value.businessId,
//   (newVal) => {
//     metadataLibrarys.value = [];
//     formInfo.value.databaseId = '';
//     newVal && getMetadataLibrary(newVal);
//   },
//   { deep: true, immediate: true }
// );

onMounted(() => {
  getUserList('');
  getBusinessSceneList();
  // getMetadataLibrary();
});
defineExpose({
  titleMap,
  sheetsDataMap,
  loadFile,
  formInfo,
  isSceneOrDatabaseChange,
  form1Ref,
  form2Ref
});
</script>
<style lang="scss" scoped>
@import "../index.scss";
.choose-file {
  flex: 1;
  // overflow: scroll;
  padding-top: 10px;
  margin-left: 20px;
  margin-right: 20px;
  height: calc(100vh - 84px);
  .form_class {
    border: 1px solid #dddddd7a;
    padding: 10px;
    margin-top: 10px;
    margin-bottom: 10px;
    .form_input {
      width: 180px;
    }
  }
  .table_div {
    margin-top: 10px;
  }
  .load-excel {
    margin-top: 20px;
  }
  .sheet-tabs {
    margin-top: 10px;
  }
}
.result-all {
  display: flex;
  .left-params {
    flex: 0 0 350px;
    margin-right: 20px;
    .des {
      height: 24px;
      line-height: 24px;
      font-weight: 500;
    }
  }
  .right-result {
    flex: 1;
  }
}
</style>